#include "GfxDriver/WGL/WGLIndexBuffer.h"

#include "GfxDriver/GfxDriver.h"
#include "Core/LogService.h"

namespace Orca {

	WGLIndexBuffer* WGLIndexBuffer::create(
		GfxDriver *gfxDriver,
		uint32 sizeInBytes,
		bool staticUsage) {

		gfxDriver->resetErrors();

		GLenum glUsage;

		if(staticUsage)
			glUsage = GL_STATIC_DRAW;
		else
			glUsage = GL_DYNAMIC_DRAW;

		GLuint glHandle;
		glGenBuffers(1, &glHandle);

		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glHandle);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)sizeInBytes, NULL, glUsage);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

		if( GL_NO_ERROR != glGetError() ) {

			LOG_ERR(
				"WGLGfxDriver: Failed to create index buffer\n"
				"\tReason: glBufferData failed" );

			glDeleteBuffers(1, &glHandle);

			return NULL;
		}

		WGLIndexBuffer *ib = new WGLIndexBuffer(gfxDriver, sizeInBytes, glHandle, glUsage);

		LOG_MSG(
			"WGLGfxDriver: Index Buffer with " + toStr(sizeInBytes) + " bytes created;"
			"glHandle=" + toStr((uint32)glHandle) );

		return ib;

	}

	//--------------------------------------------------------------------------
	WGLIndexBuffer::WGLIndexBuffer(
		GfxDriver *gfxDriver,
		uint32 sizeInBytes,
		GLuint glHandle,
		GLenum glUsage) :
		mGfxDriver(gfxDriver),
		mSizeInBytes(sizeInBytes),
		mGLHandle(glHandle),
		mGLUsage(glUsage) {

	}

	//--------------------------------------------------------------------------
	WGLIndexBuffer::~WGLIndexBuffer() {
		glDeleteBuffers(1, &mGLHandle);
	}

	//--------------------------------------------------------------------------
	uint32 WGLIndexBuffer::getSizeInBytes() {
		return mSizeInBytes;
	}

	//--------------------------------------------------------------------------
	unsigned int WGLIndexBuffer::getAPIHandle() {
		return mGLHandle;
	}

	//--------------------------------------------------------------------------
	uint8* WGLIndexBuffer::requestUpload(bool discardCurrent) {

		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLHandle);

		if(discardCurrent)
			glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)mSizeInBytes, NULL, mGLUsage);

		return (uint8*)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
	}

	//--------------------------------------------------------------------------
	void WGLIndexBuffer::uploadToGPU() {

		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLHandle);
		glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);

		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
	}

}